import org.antlr.v4.runtime.atn.SemanticContext;

import javax.crypto.ExemptionMechanism;
import java.util.ArrayList;
import java.util.List;

public class Expr
{
    public String name;
}

class Id extends Expr
{
    Object object;
    Id()
    {
    }

    Id(String name)
    {
        this.name = name;
    }
}

class SelectorExpr extends Expr
{
    Expr expr;
    Id sel;
}

enum OP
{
    Def,  // :
    Not,  // !
    Recv, // <-
    OrOr, // ||
    AndAnd, // &&
    Eql, // ==
    Neq, // !=
    Lss, // <
    Leq, // <=
    Gtr, // >
    Geq, // >=
    Add, // +
    Sub, // -
    AddAdd, // ++
    SubSub, // --
    Or,  // |
    Xor, // ^
    Mul,    // *
    Div,    // /
    Mod,   // %
    And,    // &
    AndNot, // &^
    Shl,    // <<
    Shr,    // >>
    Eq // =
};

class Expression extends Expr
{
    Expr A;
    Expr B;
    OP op;
}

class UnaryExpr extends Expr
{
    Expr x;
    OP op;
}

enum LitKind
{
    DecimalInt,
    BinaryInt,
    HexInt,
    OctalInt,
    Float,
    ImaginaryInt,
    RuneInt,
    String,
    Add,
    Sub,
    And
};

class BasicLit extends Expr
{
    String value;
    LitKind kind;
}

class KeyValueExpr extends Expr
{
    Expr key;
    Expr value;
}

class Ellipsis extends Expr
{
    Expr x;
}

class CompositeExpr extends Expr
{
    Expr type;
    List<Expr> list;
    CompositeExpr()
    {
        list = new ArrayList<>();
    }
}

class CompositeLit extends Expr
{
    Expr type;
    List<Expr> value;
    CompositeLit(){value = new ArrayList<>();}
}

class Field extends Expr
{
    Expr type;
    Id id;
    int offset = 0;
}

class StarType extends Expr
{
    Expr type;
}

class StructExpr extends Expr
{
    List<Field> fields;
    List<BasicLit> tags;
    int size;
    StructExpr()
    {
        size = 0;
        fields = new ArrayList<>();
        tags = new ArrayList<>();
    }
}

class ArrayType extends Expr
{
    Expr len;
    Expr type;
}

class FuncType extends Expr
{
    List<Field> params;
    List<Field> results;
    FuncType()
    {
        params = new ArrayList<>();
        results = new ArrayList<>();
    }
}

class CallExpr extends Expr
{
    Expr func;
    List<Expr> args;
    boolean hasDot;
    CallExpr(){args = new ArrayList<>();}
}

class InterfaceType extends Expr
{
    List<Field> methods;
    InterfaceType()
    {
        methods = new ArrayList<>();
    }
}

class SliceExpr extends Expr
{
    Expr x;
    Expr[] index;
    boolean slice3;

    SliceExpr()
    {
        index = new Expr[3];
    }
}

class MapType extends Expr
{
    Expr keyType;
    Expr valueType;
}

class ChannelType extends Expr
{
    enum ChannelDir{TWO, SEND, RECEIVE};
    ChannelDir dir;
    Expr type;
}

class Decl
{

}

class ValueDecl extends Decl
{
    List<Id> names;
    Expr type;
    List<Expr> value;
    boolean isConst;
    boolean isMulti;
    List<Expr> types;
    ValueDecl()
    {
        names = new ArrayList<>();
        value = new ArrayList<>();
        isConst = false;
        isMulti = false;
        types = new ArrayList<>();
    }
}

class TypeDecl extends Decl
{
    Id id;
    Expr type;
    boolean isAssign;
}

class Statement
{}

class LabelStatement extends Statement
{
    Id label;
    Statement statement;
}

class SendStatement extends Statement
{
    Expr channel;
    Expr value;
}

class IncDecStatement extends Statement
{
    Expr x;
    OP op;
}

class AssignStatement extends Statement
{
    List<Expr> left;
    List<Expr> right;
    OP op;
    boolean isRange;
    AssignStatement()
    {
        left = new ArrayList<>();
        right = new ArrayList<>();
        isRange = false;
    }
}

class ExpressionStatement extends Statement
{
    Expr expr;
}

class EmptyStatement extends Statement{}

class CallStatement extends Statement
{
    enum CallType{GO, DEFER};
    Expr dest;
    CallType type;
}

class ReturnStatement extends Statement
{
    List<Expr> results;
    ReturnStatement(){results = new ArrayList<>();}
}

class JumpStatement extends Statement
{
    enum JumpType{BREAK, CONTINUE, GOTO, Fallthrough};
    Id label;
    JumpType type;
}

class BlockStatement extends Statement
{
    List<Statement> list;
    BlockStatement(){list = new ArrayList<>();}
}

class IFStatement extends Statement
{
    Expr condition;
    Statement init;
    BlockStatement block;
    Statement elsePart;
}

class TypeSwitchGuard extends Statement
{
    Id name;
    Expr expr;
}

class CaseStatement extends Statement
{
    List<Expr> cases;
    List<Statement> body;
    CaseStatement(){cases = new ArrayList<>(); body = new ArrayList<>();}
}

class TypeSwitchStatement extends Statement
{
    Statement init;
    TypeSwitchGuard tag;
    List<CaseStatement> body;
    TypeSwitchStatement(){body = new ArrayList<>();}
}

class CommonClause extends Statement
{
    Statement common;
    List<Statement> body;
    CommonClause(){body=new ArrayList<>();}
}

class SelectStatement extends Statement
{
    List<CommonClause> body;
    SelectStatement(){body = new ArrayList<>();}
}

class RangeClause extends Statement
{
    List<Expr> left;
    boolean define;
    Expr expr;
    RangeClause(){left = new ArrayList<>();}
}

class ForStatement extends Statement
{
    Statement init;
    Statement post;
    Expr cond;
    BlockStatement body;
}

class DeclStatement extends Statement
{
    List<Decl> decls;
    DeclStatement(){decls = new ArrayList<>();}
}

class Signature extends Expr
{
    List<Field> param;
    List<Field> results;

    Signature()
    {
        param = new ArrayList<>();
        results = new ArrayList<>();
    }
}

class FunctionLit extends Expr
{
    Signature signature;
    BlockStatement block;
}

class IndexExpr extends Expr
{
    Expr x;
    Expr index;
}

class TypeAssertExpr extends Expr
{
    Expr x;
    Expr type;
}

class FuncDecl extends Decl
{
    List<Field> receiver;
    Id name;
    FuncType type;
    BlockStatement body;
    FuncDecl()
    {
        receiver =  new ArrayList<>();
        name = new Id();
        type = new FuncType();
        body = new BlockStatement();
    }
}